/*
*    Qizx/open 3.0 beta
*
* This code is the open-source version of Qizx.
* Copyright (C) 2004-2009 Axyana Software -- All rights reserved.
*
* The contents of this file are subject to the Mozilla Public License 
*  Version 1.1 (the "License"); you may not use this file except in 
*  compliance with the License. You may obtain a copy of the License at
*  http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
*  WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
*  for the specific language governing rights and limitations under the
*  License.
*
* The Initial Developer of the Original Code is Xavier Franc - Axyana Software.
*
*/
using System;
using System.Xml;
using QName = System.Qizx.Api.QName;
using NamespaceContext = System.Qizx.Util.NamespaceContext;
namespace System.Qizx.Xdm {

    /// <summary>
    /// Internal representation of a Qualified Name: Namespace + localName.
    /// IQName has a unique representation: comparison can be
    /// performed with ==; The prefix is always null.
    /// </summary>
    [Serializable]
    public sealed class IQName : QName {



        public override string Prefix {
            get {
                return null;
            }
        }

        /// <summary>the xml:lang qualified name </summary>
        public static IQName XML_LANG;

        /// <summary>the xml:space qualified name </summary>
        public static IQName XML_SPACE;

        /// <summary>the xml:base qualified name </summary>
        public static IQName XML_BASE;

        /// <summary>the xml:base qualified name </summary>
        public static IQName XML_ID;

        /// <summary>the xsi:type qualified name </summary>
        public static IQName XSI_TYPE;

        /// <summary>the xsi:nil qualified name </summary>
        public static IQName XSI_NIL;

        /// <summary>the xsi:schemaLocation qualified name </summary>
        public static IQName XSI_SCHEMA_LOCATION;

        /// <summary>the xsi:noNamespaceSchemaLocation qualified name </summary>
        public static IQName XSI_NO_NAMESPACE_SCHEMA_LOCATION;

        public const string NULL_NS = "";

        // ------------------------------------------------------------------------

        private static System.Collections.Generic.Dictionary<IQName, IQName> _names = new Collections.Generic.Dictionary<IQName, IQName>();
        private static IQName probe = new IQName(string.Empty, string.Empty);

        // ------------------------------------------------------------------------

        // Summary:
        //     Initializes a new instance of the System.Xml.XmlQualifiedName class.
        public IQName() : base() { }
        //
        // Summary:
        //     Initializes a new instance of the System.Xml.XmlQualifiedName class with
        //     the specified name.
        //
        // Parameters:
        //   name:
        //     The local name to use as the name of the System.Xml.XmlQualifiedName object.
        public IQName(string name) : base(name) { }
        //
        // Summary:
        //     Initializes a new instance of the System.Xml.XmlQualifiedName class with
        //     the specified name and namespace.
        //
        // Parameters:
        //   name:
        //     The local name to use as the name of the System.Xml.XmlQualifiedName object.
        //
        //   ns:
        //     The namespace for the System.Xml.XmlQualifiedName object.
        public IQName(string name, string ns) : base(name, ns) { }

        /// <summary> Obtains a unique representation of a QName from a namespace URI and a
        /// NCname.
        /// </summary>
        public static IQName GetQName(string namespaceURI, string localName) {
            lock (typeof(System.Qizx.Xdm.IQName)) {
                if (namespaceURI == null)
                    namespaceURI = string.Empty;
                namespaceURI = NamespaceContext.unique(namespaceURI);

                if (localName == null)
                    localName = string.Empty;

                // probe.Namespace = namespaceURI;
                // probe.Name = localName;
                // XmlQualifiedName cannot changed.
                IQName probe = new IQName(localName, namespaceURI);

                IQName name = null;
                if (_names.TryGetValue(probe, out name)) {
                    return name;
                }

                _names[probe] = probe;
                return probe;
            }
        }

        /// <summary> Obtains a unique representation of a QName with empty namespace.</summary>
        public static IQName GetQName(string localName) {
            lock (typeof(System.Qizx.Xdm.IQName)) {
                return GetQName("", localName);
            }
        }

        /// <summary> Internalize any QName.</summary>
        public static IQName GetQName(XmlQualifiedName name) {
            IQName iname = name as IQName;
            if (iname != null)
                return iname;
            return GetQName(name.Namespace, name.Name);
        }


        // assumes component are interned
        private static IQName CreateQName(string namespaceURI, string localName) {
            return new IQName(localName, NamespaceContext.unique(namespaceURI));
        }

        // Deserialization must give unique instance
        internal System.Object readResolve()
            //throws ObjectStreamException
        {
            return GetQName(this.Namespace, this.Name);
        }

        public int CompareTo(IQName other) {
            int cmp = this.Namespace.CompareTo(other.Namespace);
            if (cmp == 0) {
                return string.CompareOrdinal(this.Name, other.Name);
            }
            return cmp;
        }

        static IQName() {
            {
                XML_ID = GetQName(NamespaceContext.XML, "id");
                XML_LANG = GetQName(NamespaceContext.XML, "lang");
                XML_SPACE = GetQName(NamespaceContext.XML, "space");
                XML_BASE = GetQName(NamespaceContext.XML, "base");
                XSI_TYPE = GetQName(NamespaceContext.XSI, "type");
                XSI_NIL = GetQName(NamespaceContext.XSI, "nil");
                XSI_SCHEMA_LOCATION = GetQName(NamespaceContext.XSI, "schemaLocation");
                XSI_NO_NAMESPACE_SCHEMA_LOCATION = GetQName(NamespaceContext.XSI, "noNamespaceSchemaLocation");
            }
        }
    }
}